package com.zbj.homemade.spring.beans;

import com.zbj.homemade.spring.annotation.Autowired;
import com.zbj.homemade.spring.annotation.Lazy;
import com.zbj.homemade.spring.annotation.Scope;
import com.zbj.homemade.spring.annotation.Value;
import com.zbj.homemade.spring.utils.AnnoUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * |                    .  ’   *   ‘  .
 * |               _6                    "     o0000o
 * |  o00o _    .%                         %. o0000000o
 * | o000000o.:                              :(0000000o
 * | o00000os                                  .000000o
 * |  o0000/     <b>不了不了,改需求真的伤身体</>   .000o
 * |    o0o                                       .0o
 * |     y        <b>我认为源代码,就是SkrSkr</>     .
 * |    y                                           ,
 * |   y          <b>小熊猫保佑,代码永不修改</>        ,
 * |   p                            .                 .
 * |   p                           @@.                .
 * |    y                        ;@@@;               .
 * |    \                       ;@@@@;.@.          ,;S
 * |     、                     .@@@@@@;       ,@@@@@
 * |     @\.            .****...*@@@@;     .@@@@@@@@@@@.
 * |    @@@@\.     . @@@@@@@@@@@@@@@;    .@@@@@@@@@@@@@@@.
 * |   @@@@@@@@@.@@@@@@@@@@@@@@@@;   .@@@@@@@@@@@@@@@@@@@@@.
 * |  @@@@@@..@@@@..@@@@@@..@@@@@ .@@...@@@@@..@@..@@@@@..@@.
 * | @@@@@@@@..@..@@@@@@@@@@@@@;.@@@..@..@@@..@@....@@@..@@@@.
 * |@y@@@@@@@@..@@@@@@@@..@@@@i@@@@..@@@..@..@@..@@..@..@@@@n@.
 * |@n@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@...@@..@@@@...@@@@@n@@.
 * |@@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@@@.@@..@@@@@..@@@@@@@@@@.
 * |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
 *
 * @program: principle
 * @description:
 * @author: Yinn
 * @create: 2019-02-28 16:47
 **/
public class SimpleBeanDefinition implements BeanDefinition {

    /**
     * 懒加载标志，默认否
     */
    private boolean lazyInit = false;

    /**
     * 作用域 默认单例
     */
    private String scope = BeanDefinition.SCOPE_SINGLETON;

    /**
     * bean class(最后通过此类型 反射实例化对象)
     */
    private Class<?> beanClass;

    /**
     * 属性值
     */
    private List<PropertyValue> propertyValues;

    public SimpleBeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
        this.propertyValues = new ArrayList<>();

        if (AnnoUtils.isClazzAnnotated(beanClass,Lazy.class)){
            lazyInit = true;
        }

        //解析作用域
        Scope scope = beanClass.getAnnotation(Scope.class);
        if (scope != null){
            String sp = scope.value();
            if (StringUtils.isNotBlank(sp) && BeanDefinition.SCOPE_PROTOTYPE.equals(sp))
                this.scope = BeanDefinition.SCOPE_PROTOTYPE;
        }

        //解析自动注入注解 与 value注解
        for (Field field : beanClass.getDeclaredFields()) {
            PropertyValue pv = null;

            //基本类型会报错
            if (field.isAnnotationPresent(Autowired.class)) {
                pv = new PropertyValue(field, null, true, field.getType());
            }

            //todo 暂时处理字符串
            if (field.isAnnotationPresent(Value.class)) {
                Value v = field.getAnnotation(Value.class);
                pv = new PropertyValue(field, v.value(), false, field.getType());
            }

            if (pv != null)
                this.propertyValues.add(pv);

        }
    }

    @Override
    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    @Override
    public void setScope(String scope) {
        this.scope = scope;
    }

    @Override
    public boolean getLazyInit() {
        return this.lazyInit;
    }

    @Override
    public String getScope() {
        return this.scope;
    }

    @Override
    public Class<?> getBeanClass() {
        return this.beanClass;
    }

    @Override
    public boolean hasPropertyValue() {
        return this.propertyValues != null && this.propertyValues.size() > 0;
    }

    @Override
    public List<PropertyValue> propertyValues() {
        return this.propertyValues;
    }
}
